package com.pablosz.worm.components;

import java.util.ArrayList;

import android.graphics.Canvas;
import android.graphics.Paint;

import com.pablosz.worm.Lifecicle;
import com.pablosz.worm.LifecicleComponent;
import com.pablosz.worm.util.LifecicleComponents;
import com.pablosz.worm.util.Point;


public class Worm extends LifecicleComponent
{	
	// constantes
	private static final int DIRECTION_TO_LEFT = 1;
	private static final int DIRECTION_TO_RIGHT = 2;
	private static final int DIRECTION_TO_UP = 3;
	private static final int DIRECTION_TO_DOWN = 4;
	
	private int moving=DIRECTION_TO_RIGHT;
		
    // parametros
	private int radio;
	private int color;
	private int steep;
	private int size;
	
	private int currSize;
	private int originalDelay;
	
	private int increaseUnitSize;
	
	private long MAX_WIDTH;
	private long MAX_HEIGHT;
	private long MIN_WIDTH;
	private long MIN_HEIGHT;
	
	private ArrayList<Point> printed = null;
	
	private long currX=-1;
	private long currY=-1;
	private long requestedX=-1,requestedY=-1;
	
	private transient Paint paint = null;
	
	private int margin = 0;

	public Worm()
	{
		printed = new ArrayList<Point>();
		
		// definimos pincel
		paint = new Paint();
		paint.setStyle(Paint.Style.FILL);
	}
	
	@Override
	public void print(Canvas canvas)
	{
		for(int i=0; i<printed.size();i++)
		{
			Point p=printed.get(i);
			canvas.drawCircle(p.x, p.y, radio, paint);	
		}
	}
	
	private boolean redirectionRequested()
	{
		if( !isTouchOutOfBound(requestedX, requestedY) )
		{
			return requestedX>=0 && requestedY>=0;
		}
		return false;
	}

	private boolean isCorner()
	{
		// superior derecha
		if( currY<=MIN_HEIGHT && currX >= MAX_WIDTH)
		{
			moving=DIRECTION_TO_LEFT; 
			currY=MIN_HEIGHT;
			currX=MAX_WIDTH;
			return true;
		}

		//	superior izquierda
		if( currY<=MIN_HEIGHT && currX<=MIN_WIDTH)
		{
			moving=DIRECTION_TO_DOWN; 
			currY=MIN_HEIGHT;
			currX=MIN_WIDTH;
			return true;
		}			
		
		//inferior izquierda		
		if( currY>=MAX_HEIGHT && currX<=MIN_WIDTH)
		{
			moving=DIRECTION_TO_RIGHT; 
			currY=MAX_HEIGHT;
			currX=MIN_WIDTH;
			return true;
		}			
		
		//inferior derecha
		if( currY>=MAX_HEIGHT && currX>=MAX_WIDTH)
		{
			moving=DIRECTION_TO_UP; 
			currY=MAX_HEIGHT;
			currX=MAX_WIDTH;
			return true;
		}	
		
		return false;
	}

	public boolean isEating(Fruit fruit)
	{
		double dist = Math.sqrt(Math.pow(currX-fruit.getX(), 2)+Math.pow(currY-fruit.getY(), 2));
		double sumRadios = radio + fruit.getRadio();
		
		return dist <= sumRadios;
	}

	public int getRadio()
	{
		return radio;
	}

	public boolean isDead()
	{
		for(int i=0; i<printed.size()-1;i++)
		{
			
			if(currX==printed.get(i).x&&currY==printed.get(i).y)
			{
				return true;
			}
		}
		
		return false;
	}

	public int getMargin()
	{
		return margin;
	}

	public void setMargin(int margin)
	{
		this.margin = margin;
	}

	@Override
	public void init(Lifecicle lf,LifecicleComponents components,long width, long height)
	{
		MAX_WIDTH = width-radio*2-margin/2;
		MIN_WIDTH = radio*2+margin/2;
		MAX_HEIGHT = height-radio*2-margin/2;
		MIN_HEIGHT = radio*2+margin/2;
		
		currX = width/2;
		currY = height/2;
		
		printed.clear();
		currSize = size;
		resetLifecicleDelay();
		
		moving = DIRECTION_TO_RIGHT;
		
		for(int i=0; i<currSize; i++)
		{
			printed.add(new Point((int)currX,(int)currY));
			currX+=steep;
		}
				
		currX-=steep;
	}

	@Override
	public void process(Lifecicle lf,LifecicleComponents components,long width,long height)
	{
		if( redirectionRequested() )
		{			
			if( moving==DIRECTION_TO_LEFT || moving==DIRECTION_TO_RIGHT )
			{
				if( requestedY>=currY ){ moving=DIRECTION_TO_DOWN; };
				if( requestedY<=currY ){ moving=DIRECTION_TO_UP; };
			}
			else
			{
				if( requestedX>=currX ){ moving=DIRECTION_TO_RIGHT; };
				if( requestedX<=currX ){ moving=DIRECTION_TO_LEFT; };					
			}	
			
			requestedX=-1;
			requestedY=-1;
		}
		
		Point p = null;
		if( printed.size()>=currSize )
		{
			p = printed.remove(0);
		}
		
		// doy el proximo paso segun la direccion
		if( moving==DIRECTION_TO_UP ){ currY-=steep; };
		if( moving==DIRECTION_TO_DOWN ){ currY+=steep; };
		if( moving==DIRECTION_TO_LEFT ){ currX-=steep; };
		if( moving==DIRECTION_TO_RIGHT ){ currX+=steep; };
		
		if( !isCorner() )
		{
			// verifique que no se vaya de la pantalla
			if( currY<=MIN_HEIGHT) { moving=DIRECTION_TO_LEFT;}// currY=MIN_HEIGHT;};
			if( currY>=MAX_HEIGHT) { moving=DIRECTION_TO_RIGHT;}// currY=MAX_HEIGHT; };
			if( currX<=MIN_WIDTH) { moving=DIRECTION_TO_DOWN; }//currX=MIN_WIDTH; };
			if( currX>=MAX_WIDTH) { moving=DIRECTION_TO_UP; }//currX=MAX_WIDTH; };			
		}
		
		p = (p==null)?new Point():p;
		
		p.x = currX;
		p.y = currY;
		
		printed.add(p);
	}
	
	private boolean isTouchOutOfBound(long x,long y)
	{
		return x>MAX_WIDTH||x<MIN_WIDTH||y>MAX_HEIGHT||y<MIN_HEIGHT;
	}

	@Override
	public void onTouch(Lifecicle lf,LifecicleComponents components,long x,long y)
	{
		requestedX = x;
		requestedY = y;			
	}
	
	@Override
	public boolean finish(Lifecicle lf,LifecicleComponents components,long width,long height)
	{
		return true;
	}

	public void setRadio(int i)
	{
		radio = i;
	}

	public void setColor(int i)
	{
		color = i;
		paint.setColor(color);
	}

	public void setSteep(int i)
	{
		steep = i;
	}

	public void setSize(int i)
	{
		size=i;
	}
	

	public int getCurrentSize()
	{
		return currSize;
	}



	public int getIncreaseUnitSize()
	{
		return increaseUnitSize;
	}

	public void setIncreaseUnitSize(int sizeUnit)
	{
		this.increaseUnitSize = sizeUnit;
	}
	
	public long getCurrX()
	{
		return currX;
	}
	
	public long getCurrY()
	{
		return currY;
	}
	
	public int getSteep()
	{
		return steep;
	}

	public void increaseSize()
	{
		currSize+=increaseUnitSize;
	}
	
	public void reduceLifecicleDelay(int n)
	{
		setLifecicleDelay(getLifecicleDelay()-n);
	}
}
